package message.visitor;

import message.types.data.AddDataRequest;
import message.types.data.GetAllDatasAnswer;
import message.types.data.GetLastDataAnswer;
import message.types.message.RejectedRequest;
import message.types.none.GetAllDatasRequest;
import message.types.none.GetLastDataRequest;
import message.types.none.NewDataNotification;
import message.types.stalker.RegisterRequest;
import message.types.unique.EmptyMessage;
import message.types.unique.RoomInvitation;
import stalker.room.Room;
import stalker.room.RoomAction;

public class DefaultRoomMessageVisitor extends MessageVisitor<Void> {
  
  Room room_;
  
  /**
   * Contructs a visitor that works on a particular room
   * @requires room not null
   * @param room the particular room to be worked upon
   */
  public DefaultRoomMessageVisitor(Room room) {
    assert room != null;
    room_ = room;
  }
  
  @Override
  public Void visit(AddDataRequest addDataReq) {
    
    assert (addDataReq.getDestination().equals(room_));
    if (room_.getRoomUsers().isAuthorized(addDataReq.getClient(), RoomAction.kWrite)) {
      // authorized
      room_.getDatas().addData(addDataReq.getClient(), addDataReq.getContent());
      room_.getRoomUsers().broadCast(room_);
    } else {
      room_.acceptMessage(getRejectedMessage(addDataReq));
    }
    
    return null;
  }

  @Override
  public Void visit(GetLastDataRequest getLastReq) {
    
    assert (getLastReq.getDestination().equals(room_));
    
    if (room_.getRoomUsers().isAuthorized(getLastReq.getClient(), RoomAction.kRead)) {
      //authorized
      
      if (room_.getDatas().isEmpty()) {
        return null;
      }
      // reply
      getLastReq.getClient().acceptMessage(new GetLastDataAnswer(
          room_, getLastReq.getClient(), room_.getDatas().retrieveLatestData()));
    } else {
      //not authorized
      room_.acceptMessage(getRejectedMessage(getLastReq));
    }
    
    return null;
  }

  @Override
  public Void visit(RegisterRequest getRegisterReq) {
    assert getRegisterReq != null;
    if (room_.getRoomUsers().isAuthorized(getRegisterReq.getClient(), RoomAction.kRegister)) {
      // authorized
      room_.getRoomUsers().addUser(getRegisterReq.getStalker());
      getRegisterReq.getStalker().acceptMessage(
          new RoomInvitation(
              room_, // from
              getRegisterReq.getStalker(), // to
              room_, // location
              getRegisterReq.getClient())); // inviter
      // room_.acceptMessage(new AddDataRequest(getRegisterReq.getClient(),
      //                     room_, new ContentStalkerJoin(getRegisterReq.getStalker())));
    } else {
      // not authorized
      room_.acceptMessage(getRejectedMessage(getRegisterReq));
    }
    return null;
  }

  @Override
  public Void visit(EmptyMessage getEmptyMsg) {
    return null;
  }

  @Override
  public Void visit(RoomInvitation roomInvit) {
    assert roomInvit != null;
    relayMessage(roomInvit);
    return null;
  }

  @Override
  public Void visit(GetAllDatasRequest getAllData) {
    assert (getAllData.getDestination().equals(room_));
    
    if (room_.getRoomUsers().isAuthorized(getAllData.getClient(), RoomAction.kReadAll)) {
      // authorized
      // reply
      getAllData.getClient().acceptMessage(new GetAllDatasAnswer(
          room_, getAllData.getClient(), room_.getDatas()));
      return null;
    } else {
      // not authorized
      room_.acceptMessage(getRejectedMessage(getAllData));
      return null;
    }
  }

  @Override
  public Void visit(GetAllDatasAnswer getAllAns) {
    assert getAllAns != null;
    relayMessage(getAllAns);
    return null;
  }

  @Override
  public Void visit(NewDataNotification newDataNotif) {
    assert newDataNotif != null;
    relayMessage(newDataNotif);
    return null;
  }

  @Override
  public Void visit(RejectedRequest rejectedRequest) {
    
    assert rejectedRequest != null;
    
    if (rejectedRequest.getDestination().equals(room_)) {
      // message arrived
      assert false;
    } else {
      relayMessage(rejectedRequest);
    }
    
    return null;
  }
  
}
